package practica1.ui;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.util.ArrayList;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import practica1.Practica1;
import practica1.controller.*;
import practica1.domain.SimulacionBacteriasEvent;
import practica1.domain.SimulacionBacteriasListener;
import practica1.logic.LogicExperimento;
import practica1.logic.LogicPoblacion;
import practica1.manejoExperimento.ManejoExperimento;
import practica1.manejoExperimento.ManejoExperimentoAdapter;
import practica1.util.Utils;


/**
 *
 * @author Miguel González - Ceura
 */
public class BarraEstado extends JPanel {
    private OcultarMensaje ocultarMensaje;
    private JLabel lblHora;
    private JLabel lblAccion;
    private JComboBox cboSimulando;
    private BarraEstadoModel modelCboSimulando;
    
    public BarraEstado() {
        initComponents();
        
        initSwing();
        
        initListeners();
        
        initThreads();
    }
    
    private void initThreads() {
        Reloj reloj = new Reloj();
        reloj.start();
    }
    
    private void initComponents() {
        ocultarMensaje = null;
        modelCboSimulando = new BarraEstadoModel(
                new String[]{"No hay simulaciones activas"});
        cboSimulando = new JComboBox(modelCboSimulando);
        
        lblHora = new JLabel(Utils.getHora());
        lblAccion = new JLabel();
    }
    
    private void initSwing() {
        JPanel panelIzq = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panelIzq.add(lblAccion);
        add(panelIzq);
        
        JPanel panelDcho = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panelDcho.add(lblHora);
        panelDcho.add(cboSimulando);
        
        setLayout(new BorderLayout());
        add(panelIzq, BorderLayout.WEST);
        add(panelDcho, BorderLayout.EAST);
    }

    private void initListeners() {
        Controller.getInstance().addControllerPoblacionListener(
                new EscuchadorPoblaciones());
        Controller.getInstance().addControllerExperimentoListener(
                new EscuchadorExperimentos());
        
        ManejoExperimento.addManejoExperimentoListener(new EscuchadorGuardado());
    }
    
    private class EscuchadorPoblaciones extends ControllerPoblacionAdapter {
        @Override
        public void addedPoblacion(ControllerPoblacionEvent evt) {
            //Escuchamos la población
            evt.getPoblacion().getSimulacionBacterias().addSimulacionBacteriasListener(
                    new EscuchadorSimulacion(evt.getPoblacion()));
        }
    }
    
    private class EscuchadorExperimentos extends ControllerExperimentoAdapter {
        @Override
        public void addedExperimento(ControllerExperimentoEvent event) {
            ArrayList<LogicPoblacion> poblaciones = 
                    event.getExperimento().getPoblaciones();
            
            for(LogicPoblacion p : poblaciones) {
                p.getSimulacionBacterias().addSimulacionBacteriasListener(
                    new EscuchadorSimulacion(p));
            }
        }
    }
    
    private class EscuchadorSimulacion implements SimulacionBacteriasListener {

        private LogicPoblacion poblacion;
        
        public EscuchadorSimulacion(LogicPoblacion poblacion) {
            this.poblacion = poblacion;
        }
        
        @Override
        public void simulacionBacteriasChange(SimulacionBacteriasEvent evt) {}

        @Override
        public void terminadaSimulacion() {
            int cantSimulando = modelCboSimulando.getSize() - 2;
            
            if(cantSimulando == 0) {
                modelCboSimulando.setElementAt(0, "No hay simulaciones activas");
            } else {
                modelCboSimulando.setElementAt(0, "Simulaciones activas: " + cantSimulando);
            }
            
            modelCboSimulando.removeElement("Simulando: " + 
                    poblacion.getNombrePoblacion());
        }

        @Override
        public void simulacionAcabadaDia(int numDia, int [][]comidaDia, 
            int [][]bacteriasDia) {
        }

        @Override
        public void empezadaSimulacion() {
            int cantSimulando = modelCboSimulando.getSize();
            modelCboSimulando.setElementAt(0, "Simulaciones activas: "
                    + cantSimulando);
            modelCboSimulando.addElement("Simulando: " +
                    poblacion.getNombrePoblacion());
        }
    }
    
    private class Reloj extends Thread {
        @Override
        public void run() {
            while(true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    Practica1.log.error("Error InterruptedException en el reloj", ex);
                }
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        lblHora.setText(Utils.getHora());
                    }                
                });
            }
        }
    }
    
    private class EscuchadorGuardado extends ManejoExperimentoAdapter {
        private void lanzarMensaje(String mensaje) {
            if(ocultarMensaje != null) {
                ocultarMensaje.cancelarAccion();
            }
            
            lblAccion.setText(mensaje);
            
            ocultarMensaje = new OcultarMensaje();
            ocultarMensaje.start();
        }
        
        @Override
        public void guardadoExperimento(LogicExperimento exp) {
            lanzarMensaje("Guardado " + exp.getNombreExperimento());
        }
        
        @Override
        public void guardandoExperimento(LogicExperimento exp) {
            lanzarMensaje("Guardando " + exp.getNombreExperimento());
        }
        
        @Override
        public void abriendoExperimento(String rutaExp) {
            lanzarMensaje("Abriendo experimento " + rutaExp);
        }

        @Override
        public void abiertoExperimento(LogicExperimento exp) {
            lanzarMensaje("Abierto " + exp.getNombreExperimento());
        }
    }
    
    private class OcultarMensaje extends Thread {
        private boolean hacerAccion;
        
        public OcultarMensaje() {
            hacerAccion = true;
        }
        
        @Override
        public void run() {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException ex) {
                Practica1.log.error("InterruptedException error", ex);
            }
            
            if(hacerAccion) {
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        lblAccion.setText("");
                    }
                });
            }
        }
        
        public void cancelarAccion() {
            hacerAccion = false;
        }
    }
}
